package com.ylz.sjzx.sio.common.core.core.container.common;

import com.ylz.sjzx.sio.common.core.core.Interceptor.IInterceptor;
import com.ylz.sjzx.sio.common.core.core.container.common.annotation.InterceptorDesc;

import java.util.Comparator;

/**
 * Description:
 * 容器管理实例排序比较器,使用管理实例的类注释进行排序。</br>
 * 分两步进行：</br>
 * 1.查询当前compare对象的类型，如果在父亲集合里找到父类，则采用父类类型</br>
 * 2.根据类型查找合适的比较器，进行比较。
 *
 * @param <T> 需要排序的的实例类型，根据此类型会筛选合适比较器
 */
public class ContainerSortComparator<T> implements Comparator<T> {

    /**
     * 逆序排序，默认的排序方式为自然排序即1>2>3，逆序为3>2>1
     */
    private boolean desc = false;

    /**
     * 需要替换的父亲集合
     */
    private Class<? extends T>[] parentClazz;

    public ContainerSortComparator(Class<? extends T>[] parentClazz) {
        this.parentClazz = parentClazz;
    }

    @Override
    public int compare(T comparator1, T comparator2) {

        Class clazz1 = this.getClass(comparator1);
        Class clazz2 = this.getClass(comparator2);

        Comparator<Class<?>> delegate = this.getDelegate(comparator1.getClass());

        if (delegate == null) {
            return 0;
        }

        int result = delegate.compare(clazz1, clazz2);

        return this.desc ? -1 * result : result;

    }

    /**
     * 如果parentClazz中存在父亲类型，则用父亲类型替换孩子类型，用于实现排序时以父亲类型的顺序为准的规则。
     *
     * @param clazz comp
     * @return Class 这里我们不关注Class指代的类型
     */
    private Class getClass(T clazz) {

        for (Class<? extends T> parent : this.parentClazz) {

            if (parent.isAssignableFrom(clazz.getClass())) {
                return parent;
            }
        }

        return clazz.getClass();
    }

    /**
     * 获取代理比较器，代理比较器通过能够处理的class类型进行分类
     * 代理比较器基于两个Class之间做比较，通过比较Class上的注解确定排序
     *
     * @param clazz 需要处理比较的类型
     * @return Comparator 比较器
     */
    private Comparator<Class<?>> getDelegate(Class<?> clazz) {

        for (DelegateComparator delegate : DelegateComparator.values()) {
            if (delegate.getHandleClass().isAssignableFrom(clazz)) {
                return delegate.getComparator();
            }
        }

        return null;
    }

    public void setDesc(boolean desc) {
        this.desc = desc;
    }

    /**
     * 代理比较器枚举
     */
    private enum DelegateComparator {

        /**
         * Interceptor类型代理
         */
        INTERCEPTOR(IInterceptor.class, new Comparator<Class<?>>() {

            @Override
            public int compare(Class<?> c1, Class<?> c2) {
                InterceptorDesc desc1 = c1.getAnnotation(InterceptorDesc.class);
                InterceptorDesc desc2 = c2.getAnnotation(InterceptorDesc.class);

                if (desc1.order() <= desc2.order()) {
                    return -1;
                }
                return 1;
            }

        });

        /**
         * 可以处理的类型
         */
        private Class<?> handleClass;

        /**
         * 可以处理的类型对应的比较器
         */
        private Comparator<Class<?>> comparator;

        DelegateComparator(Class<?> handleClass, Comparator<Class<?>> comparator) {
            this.handleClass = handleClass;
            this.comparator = comparator;
        }

        public Class<?> getHandleClass() {
            return this.handleClass;
        }

        public Comparator<Class<?>> getComparator() {
            return this.comparator;
        }
    }

}
